home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Mac Game Programming Gurus
/
TricksOfTheMacGameProgrammingGurus.iso
/
Information
/
CSMP Digest
/
volume 1
/
csmp-v1-145.txt
< prev
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
NeXTSTEP
RISC OS/Acorn
UTF-8
Wrap
Text File
|
1994-12-08
|
44.8 KB
|
1,285 lines
|
[
TEXT/R*ch
]
C.S.M.P. Digest Sun, 19 Jul 92 Volume 1 : Issue 145
Today's Topics:
The big question...
Is "WITH anObject DO ..." dangerous in THINK Pascal ?
Mistake in THINK Pascal manual (boolean operators)
Think C and ctype
dynamic 2d arrays in THINK C?
The Comp.Sys.Mac.Programmer Digest is moderated by Michael A. Kelly.
The digest is a collection of article threads from the internet newsgroup
comp.sys.mac.programmer. It is designed for people who read c.s.m.p. semi-
regularly and want an archive of the discussions. If you don't know what a
newsgroup is, you probably don't have access to it. Ask your systems
administrator(s) for details. (This means you can't post questions to the
digest.)
Each issue of the digest contains one or more sets of articles (called
threads), with each set corresponding to a 'discussion' of a particular
subject. The articles are not edited; all articles included in this digest
are in their original posted form (as received by our news server at
cs.uoregon.edu). Article threads are not added to the digest until the last
article added to the thread is at least one month old (this is to ensure that
the thread is dead before adding it to the digest). Article threads that
consist of only one message are generally not included in the digest.
The entire digest is available for anonymous ftp from ftp.cs.uoregon.edu
[128.223.8.8] in the directory /pub/mac/csmp-digest. The most recent issues
are available from sumex-aim.stanford.edu [36.44.0.6] in the directory
/info-mac/digest/csmp. If you don't have ftp capability, the sumex archive
has a mail server; send a message with the text '$MACarch help' (no quotes)
to LISTSERV@ricevm1.rice.edu for more information.
The digest is also available via email. Just send a note saying that you
want to be on the digest mailing list to mkelly@cs.uoregon.edu, and you will
automatically receive each new issue as it is created. Sorry, back issues
are not available through the mailing list.
Send administrative mail to mkelly@cs.uoregon.edu.
-------------------------------------------------------
From: skelmir@rhi.hi.is (Mimir Reynisson)
Subject: The big question...
Date: 15 Jun 92 07:56:26 GMT
Now that the facts have come to light etc and Microsoft won the
look-and-feel suit against Apple. And that seems to be the trend
in the software business. Why not create a set of applications that
look excatly like Word, Excel, etc..? There seems to be a quite a lot of
cases that say that you would not loose in court, and not be fined either.
It seems to me that as long as you have a different set of manuals,
they cant touch you.
//S&M
+++++++++++++++++++++++++++
From: fry@tara.harvard.edu (David Fry)
Date: 15 Jun 92 11:23:22 GMT
Organization: Harvard Math Department
Microsoft has not won the lawsuit with Apple. A month or so ago
a judge threw out a large portion of Apple's suit, but then he agreed
to reconsider those parts. Last week the whole issue was postponed
until a future date. So it's not at all over yet.
As for your suggestion to make programs that work exactly like
leading applications, Borland was sued by Lotus for doing this a few
years ago over the spreadsheet Quattro, but I forget the outcome.
Anyone, anyone? I'm pretty sure Lotus lost.
David Fry fry@math.harvard.EDU
Division of Applied Sciences fry@huma1.bitnet
Harvard University ...!harvard!huma1!fry
Cambridge, MA 02138
+++++++++++++++++++++++++++
From: johnston@me.udel.edu (William Johnston)
Date: 15 Jun 92 15:03:00 GMT
Organization: University of Delaware/Department of Mechanical Engineering
In article <4945@krafla.rhi.hi.is>, skelmir@rhi.hi.is (Mimir Reynisson) writes...
>Now that the facts have come to light etc and Microsoft won the
>look-and-feel suit against Apple. And that seems to be the trend
>in the software business. Why not create a set of applications that
>look excatly like Word, Excel, etc..? [...]
Blechhh! I might agree if MS had even come *close* to matching
Apple's look and feel. Never has so much effort and money been
wasted, in my view. It doesn't matter how good the Toyota is;
some people, even _most_ people, will end up buying something
cheaper. Some will even let themselves be swayed (or assuaged)
by a salesman's suggestion that a Chevy is just as good as a
Toyota, only cheaper. And for some purposes, that may be true.
Nevertheless, one rarely sees the "Toyota" in such a scenario
spending so much effort attacking the claims of a "Chevrolet".
Why? Because ... not only is such a tactic clearly the act
of a coward/weenie (if you'll forgive my ascribing individual
traits to a group) but it also serves to legitimize the claims
of the imitator/pretender in the minds of the consumer.
The two sides will probably never reach an understanding on
this point, but *my* side-by-side comparisons of Windows and
MacOS never left me wondering which product was the "Toyota",
or rather, which was genuinely innovative and well designed.
If the point is still not clear to the boneheads in Apple
management who decided to pursue this wasteful lawsuit,
here in a nutshell is the lesson they should have learned:
1) Imitation is the highest form of flattery.
2) It is a better marketing strategy to exploit the fact
that one is being imitated than it is to attack the
imitator, either legally or by smear tactics.
Apple is a big company that has adopted a mix of sales
strategies in the Mac era. At times, various Apple ad
campaigns have practiced the above lesson effectively;
clearly, not everyone in Apple management agreed with
the Apple vs. MS & HP lawsuit tactic/strategy.
In the aftermath of the legal verdicts -- when the dust
finally clears -- Apple shareholders should take a long
look at the outcome and hold those who preached lawsuit
accountable.
I'm a (satisfed) Apple customer; all that I lost as the
result of the wasted legal expenses is that I might have
paid a bit less for Apple products and perhaps benefitted
from an even faster rate of innovation. But that's just
a guess -- who's to say that progree would have come any
faster if Apple's resources had been directed exclusively
at R&D and price competitiveness?
But if I were an Apple shareholder, I'd be asking tough
questions about the return on investment in legal costs.
If the answer demonstrates the utter stupidity of the
look-and-feel legal misadventure (as I'm sure it will)
I would demand to see heads roll.
- -- Bill (johnston@me.udel.edu)
+++++++++++++++++++++++++++
From: kfischer@mesa.llnl.gov (K. Fischer)
Date: 15 Jun 92 16:29:38 GMT
Organization: LLNL
In article <15JUN199210032745@me.udel.edu>, johnston@me.udel.edu (William Johnston) writes:
|>Blechhh! I might agree if MS had even come *close* to matching
|>Apple's look and feel. Never has so much effort and money been
|>wasted, in my view. It doesn't matter how good the Toyota is;
|>some people, even _most_ people, will end up buying something
|>cheaper. Some will even let themselves be swayed (or assuaged)
|>by a salesman's suggestion that a Chevy is just as good as a
|>Toyota, only cheaper. And for some purposes, that may be true.
I would *MUCH* rather have the Chevy, thank you very much (and I'm
not talking about computers OR software here). Just MHO :^)
Perhaps if you had said "It doesn't matter how good the domestic car
is; some people, even _most_ people, will end up buying something
imported". :^)
- --
Kathleen Fischer
kfischer@mesa.llnl.gov
"Is it true, Is it nice, Is it necessary?" <-- flame proof :^)
DISCLAIMER: Statements expressed here are mine, Mine, MINE!!!
+++++++++++++++++++++++++++
From: orpheus@reed.edu (P. Hawthorne)
Date: 16 Jun 92 23:45:21 GMT
Organization: Reed College, Portland, Oregon
skelmir@rhi.hi.is (Mimir Reynisson) writes...
. Why not create a set of appls that look excatly like Word, Excel...
Retch! Be careful what you wish for, you just might get it.
johnston@me.udel.edu (William Johnston) writes:
. I might agree if MS had even come *close* to matching Apple's look and
. feel. Never has so much effort and money been wasted, in my view.
At this point, Bill Gates has more money than he can possibly spend
before he earns that much again. Microslut is worse than the meat trusts,
and should have been dismantled by the Feds in the Eighties. The least the
FTC should do is break the operating system and compiler groups up from the
word processor and spreadsheet groups, and let them fight over who gets the
electronic mail group.
I want to see Gates in front of a Senate committee hearing yesterday,
trying to explain away the body of trust law with some palsy excuses about
standardization and the merits of centrally planned economies.
Anyone ever see the old movie The Devil and Daniel Webster? Would Gates
be Javis, Scratch himself, or the succubus from over the hills?
suitti@ima.isc.com (Stephen Uitti) writes:
. Actually, with System 7, one could claim that Apple has copied the look
. and feel of MS Windows - slow and bloated.
Speaking of Webster, NeXT's programmers must use low end NeXT hardware
for development.
Theus (orpheus@reed.edu)
+++++++++++++++++++++++++++
From: suitti@ima.isc.com (Stephen Uitti)
Organization: Interactive Systems, Cambridge, MA 02138-5302
Date: Tue, 16 Jun 1992 18:42:12 GMT
In article <15JUN199210032745@me.udel.edu> johnston@me.udel.edu (William Johnston) writes:
>In article <4945@krafla.rhi.hi.is>, skelmir@rhi.hi.is (Mimir Reynisson) writes...
>>Now that the facts have come to light etc and Microsoft won the
>>look-and-feel suit against Apple. And that seems to be the trend
>>in the software business. Why not create a set of applications that
>>look excatly like Word, Excel, etc..? [...]
>
>Blechhh! I might agree if MS had even come *close* to matching
>Apple's look and feel. Never has so much effort and money been
>wasted, in my view.
Actually, with System 7, one could claim that Apple has copied
the look and feel of MS Windows - slow and bloated.
I'm considering upgrading from System 7 to System 6.0.7.
I'd still get Truetype for my non-postscript printer, and
could still watch little tiny QuickTime movies...
Seriously, I think it's time to rewrite the finder again - this
time, using the Macintosh user interface guidelines to the
letter, and using a development system that isn't so slow and
bloated that you can only develop using a Quadra with 32 MB RAM,
and 600 MB of disk. The finder should be runable on a Mac Plus
with a 1/2 MB of RAM. C++ isn't all it was promised to be.
Stephen.
suitti@ima.isc.com
+++++++++++++++++++++++++++
From: major@bbn.com (John Major)
Date: 17 Jun 92 17:09:58 GMT
Organization: Bolt Beranek and Newman Inc., Cambridge MA
To use Telnet with MacTCP and the Comm Toolbox, use one of the third
party Connection Tools - Versaterm Telnet Tool from Synergy Software,
or TCPak from Advanced Software Concepts (a French gang). They are
both excellent. The MacTCP Tool that comes with MacX I know will only
work with MacX, and now you've told me why - "hardwired for port 6000",
eh?
Good luck -
John Major
major@bbn.com
ALINK:D6590
617/873-8165
+++++++++++++++++++++++++++
From: bilpin.co.uk (Mark Allerton)
Date: 17 Jun 92 15:51:06 GMT
Organization: SRL Data
> As for your suggestion to make programs that work exactly like
> leading applications, Borland was sued by Lotus for doing this a few
> years ago over the spreadsheet Quattro, but I forget the outcome.
> Anyone, anyone? I'm pretty sure Lotus lost.
In fact, Lotus sued Paperback software and *won*, I think you'll find
Mark Allerton
UK Macintosh Developer Technical Support
---------------------------
From: wstomv@wsinpa01.win.tue.nl (Tom Verhoeff)
Subject: Is "WITH anObject DO ..." dangerous in THINK Pascal ?
Date: 15 Jun 92 12:05:51 GMT
In several places (Inside Macintosh, THINK Pascal documentation) I have
read warnings not to rely on addresses to relocatable data structures.
For example, if H a is a Handle to some relocatable record R, then
WITH H^^ DO BEGIN
"do something that might cause R to be relocated" ;
"modify a field of R"
END
is asking for trouble, because the THINK Pascal compiler determines the
actual address of the record R once upon entry of the WITH-statement.
Relocation of R invalidates that address and, hence, further
references via this address no longer make sense.
My question now is:
Does this also hold for WITH-statements applied to objects?
The similarity between "WITH anObject DO ..." and the above is that
in THINK Pascal, an object variable is implemented as a Handle (to
the actual object, which resides in a relocatable record on the heap).
Even though you don't write it as such, "WITH anObject DO ..." is
a disguise of "WITH anObjectHandle^^ DO ...". And how about the
implicit "WITH SELF DO ..." in the body of methods?
On the other hand, since the THINK Pascal compiler might incorporate
knowledge about the particular use of WITH on objects, I can imagine
that "WITH anObject DO ..." does not suffer from the same problems
as "WITH H^^ DO ...". For instance, because once upon entry of the
WITH-statement a Handle to the object is determined (and not a direct
pointer, which gets invalidated by relocation of the object).
Can anyone shed some light on this? I have not been able to find
explicit mention of this in either Inside Mac or the THINK Pascal doc.
Tom
- --
INTERNET: wstomv@win.tue.nl / Eindhoven University of Technology
VOICE: +31 40 47 41 25 / Dept of Mathematics & Computing Science
FAX: +31 40 43 66 85 / PO Box 513, NL-5600 MB Eindhoven, Netherlands
+++++++++++++++++++++++++++
From: siegel@world.std.com (Rich Siegel)
Date: 15 Jun 92 14:02:05 GMT
Organization: GCC Technologies
In article <3542@svin02.info.win.tue.nl> wstomv@win.tue.nl writes:
[describes WITH h^^ DO...]
> Does this also hold for WITH-statements applied to objects?
Yes. It's also true for the implicit WITH SELF DO in methods, so it's
wise to have a lock method which will stack the object's current state,
move it high, and lock it, and an unlock method which will pop the last
state, and to use these calls at the beginning and end of methods or
around WITH statements.
R.
- --
- -----------------------------------------------------------------------
Rich Siegel Internet: siegel@world.std.com
Software Engineer & Toolsmith
GCC Technologies
+++++++++++++++++++++++++++
From: wstomv@wsinpa01.win.tue.nl (Tom Verhoeff)
Date: 16 Jun 92 07:48:43 GMT
Organization: Eindhoven Univ. of Technology, The Netherlands
In article <3542@svin02.info.win.tue.nl>, wstomv@win.tue.nl writes:
>In several places (Inside Macintosh, THINK Pascal documentation) I have
>read warnings not to rely on addresses to relocatable data structures.
>
>For example, if H a is a Handle to some relocatable record R, then
>
> WITH H^^ DO BEGIN
> "do something that might cause R to be relocated" ;
> "modify a field of R"
> END
>
>is asking for trouble, because the THINK Pascal compiler determines the
>actual address of the record R once upon entry of the WITH-statement.
>Relocation of R invalidates that address and, hence, further
>references via this address no longer make sense.
>
>My question now is:
>
> Does this also hold for WITH-statements applied to objects?
^^^^
(I admit, "this" is rather vague, but read on.)
So far I have had four reactions. They unanimously---but, as I now
know, incorrectly---claim that
WITH aHandle^^ DO ...
and
WITH anObject DO ...
(including the implicit "WITH SELF DO ..." surrounding bodies of methods)
are EQUALLY dangerous. Nevertheless, I have evidence to the contrary.
I carried out a little experiment to investigate the matter. This
experiment is described below.
Let me first give a summary of the result (N.B. This applies to
THINK Pascal; it need not apply to other implementations of objects):
Upon entry of "WITH aHandle^^ DO ..." a temporary POINTER
to the record is determined (once). Access of an unqualified
record field in ... involves this temporary pointer to
determine the address of the field. Record relocation may
invalidate this temporary pointer, leading to nasty bugs.
Upon entry of "WITH anObject DO ..." a temporary HANDLE (not
pointer!) to the object is determined (once). Access of an
unqualified instance variable of the object in ... involves
this temporary handle to determine the address of the instance
variable. Record relocation does NOT affect the addressing
through the temporary handle. N.B. This does NOT imply that
there are NO dangers at all with addresses of objects and
(more importantly) their instance variables (see below).
Why would you want to know this? Because, if you assume that access of
an object's instance variables in a WITH statement is equally
dangerous, then programming with objects becomes a pain. Too defensive
approaches to objects (such as avoiding WITH statements or, worse,
moving data to high memory and (un)locking etc.), make programs overly
complicated and I consider that even more dangerous. Fortunately, in
THINK Pascal there is no need to worry that much. And Symantec should
explain this in their documentation. (The only hint---if you can call
it that---I have found is on page 37 (top) of the THINK Pascal Object-Oriented
Programming Manual Version 4. Here, it is suggested that references
to instance variables, even in WITH statements, are resolved dynamically.)
Apparently, "WITH anObject DO ..." is implemented slightly less efficiently
than "WITH aHandle^^ DO ...". The reason to use "WITH anObject DO ...",
however, is not only to simplify the syntactic appearance of your programs.
Consider, for instance, a two dimensional array of objects, such as
VAR anObjectArray: ARRAY[ 0..9 , 0..9 ] OF CObject ;
then in "WITH anObjectArray[i,j] DO ..." the handle to the object
at coordinates i,j is determined only once and references to its instance
variables in the WITH statement body do NOT involve repeated indexing
in the array.
- --------------------------------------------------------------------------
Now for the EXPERIMENT. It involves the following program:
PROGRAM WithObjectTest ;
TYPE
CObject = OBJECT
InstanceVariable: integer ;
END ; { CObject }
TRecord = RECORD
Field: integer ;
END ; { TRecord }
TRecordPtr = ^TRecord ;
TRecordHandle = ^TRecordPtr ;
VAR
anObject: CObject ;
aRecordHandle: TRecordHandle ;
BEGIN { WithObjectTest }
ShowText ;
new( anObject ) ; { create an instance }
writeln( @anObject.InstanceVariable ) ;
WITH anObject DO BEGIN
writeln( InstanceVariable ) ;
MoveHHi( Handle( anObject ) ) ; { force relocation }
writeln( InstanceVariable ) ;
END ; { with }
writeln( @anObject.InstanceVariable ) ;
writeln ;
aRecordHandle := TRecordHandle( NewHandle( SizeOf( TRecord ) ) ) ;
{ create a record }
writeln( @aRecordHandle^^.Field ) ;
WITH aRecordHandle^^ DO BEGIN
writeln( Field ) ;
MoveHHi( Handle( aRecordHandle ) ) ; { force relocation }
writeln( Field ) ;
END ; { with }
writeln( @aRecordHandle^^.Field ) ;
END. { WithObjectTest }
Sample output in Text window (for one run on my machine):
004C3DC6
004C3DC6
004DB5CA
004DB5CA
004C3F10
004C3F10
004C3F10
004DB5C8
Interpretation of output:
It is to be expected that in both blocks the first two addresses
are equal (no relocation opportunity occurred in between them
(unless writeln may cause relocation; any comment?)). The output
confirms this.
The acid test is whether in each block the last two addresses
are equal. Here, we notice a clear difference.
In case of the object (hence, an implicit handle), we see that
for the second occurrence of the InstanceVariable in the WITH
statement the correct address is obtained (in spite of the
preceding relocation, which took place because the last addres
differs from the first). This is the way I think it ought to be.
In case of the explicit handle (second block), we see that
after relocation (which took place because the last address
differs from the first), the wrong (= old) address of Field
is obtained.
(The compiler can hardly be blamed because, in such cases it
does not know that the "pointer to a pointer" is actually a handle.
There is no way to write "WITH aHandle DO ...", since aHandle is
not a record.)
Conclusion:
"WITH anObject DO ..." is NOT equally dangerous as
"WITH aHandle^^ DO ...".
[NOTE: If someone can (explain to me how to) disassemble the above
program, then this might provide further insights.]
What dangers are still present when using objects? Well, since they
can be relocated, you should never rely on (the constancy of) their
addresses (or those of their instance variables). For example, the
following use is DANGEROUS (the context is that of above program):
WITH anObject DO
BadProc( InstanceVariable ) ;
where BadProc is defined by
PROCEDURE BadProc( VAR n: integer ) ;
BEGIN
"cause relocation" ;
n := 0 ;
END ; { BadProc }
The address of the actual parameter passed to BadProc is determined
before the relocation. The assignment to the actual parameter
occurs after relocation and is based on the obsolete address.
It is equally dangerous to do:
BadProc( anObject.InstanceVariable ) ;
WITH aRecordHandle^^ DO
BadProc( Field ) ;
BadProc( aRecordHandle^^.Field ) ;
Thus, this danger has nothing to do with WITH-statements!
Tom
- --
INTERNET: wstomv@win.tue.nl / Eindhoven University of Technology
VOICE: +31 40 47 41 25 / Dept of Mathematics & Computing Science
FAX: +31 40 43 66 85 / PO Box 513, NL-5600 MB Eindhoven, Netherlands
+++++++++++++++++++++++++++
From: peter@cujo.curtin.edu.au (Peter N Lewis)
Organization: NCRPDA, Curtin University
Date: Wed, 17 Jun 1992 04:04:55 GMT
In article <3542@svin02.info.win.tue.nl>, wstomv@wsinpa01.win.tue.nl (Tom Verhoeff) writes:
> Does this also hold for WITH-statements applied to objects?
> Can anyone shed some light on this? I have not been able to find
> explicit mention of this in either Inside Mac or the THINK Pascal doc.
Yes, its dangerous. Lock the object first. It is documented explicitly as
dangerous somewhere in the TP manual, I remember reading it, and have been
bitten by it before (ooops :-).
Note there are much less obvious senarios that are also dangerous or error
prone. Here is an example:
type theObject=object
s:str255;
procedure Ick;
end;
{$S Eeek}
procedure Eeek(s:str255);
begin
end;
{$S Main}
procedure theObject.Ick;
begin
Eeek(s);
end;
Eeek can receive a garbage string, even though its a value parameter. Why?
What happens is that the address of s in the object is pushed, and then
Eeek is called. But since Eek is in another segment, it may need loading,
which will invalidate the pointer, before Eeek gets a chance to copy the
string. Bad news. Obviously things would be even worse if s was a var
parameter, since the Eeek could then write garbage to the invalid address.
These aren't Symantec's fault, but I have certainly found objects to
be very dangerous, you need to be especially careful with them because
it is so easy to forget that you are referencing handle fields. Personally
I'd preffer a different (safer) implementation of objects, but since I
haven't thought of one I can't really request this...
Have fun all, and play safe! :-)
Peter.
______________________________________________________________________
Peter N Lewis, NCRPDA, Curtin University peter@cujo.curtin.edu.au
GPO Box U1987, Perth WA 6001, AUSTRALIA FAX: +61 9 367 8141
---------------------------
From: holwerda@sci.kun.nl (R.N.A. Holwerda)
Subject: Mistake in THINK Pascal manual (boolean operators)
Organization: University of Nijmegen, The Netherlands
Date: Mon, 15 Jun 1992 14:25:25 GMT
Hi there,
The Think Pascal 4.0 Manual description of the behaveour of boolean operators
is incorrect. It says that when your program evaluates
boolexprA and boolexprB
you can't be sure boolexprB will be evaluated because the result of the 'and'-
expression will be false if boolexprA eveluates to false. Then there's no need
to evaluate boolexprB.
My tests indicate that this is incorrect. Even if boolexprA returns false,
boolexprB will be evaluated. The similar thing holds for the 'or' operator.
However, when I examined the TCL-source code I found out that there is an alter-
native 'and'-operator called '&'. This operator behaves like the manual says
'and' does. For the 'or' there's the alternative '|'.
But these operators are not mentioned in the manual! At least not in the section
about operators.
Has anyone else found any errors like this in the manual, or other undocumented
features of the language or the envrinment? I'd really like to know.
Robert Holwerda,
holwerda@sci.kun.nl
P.S. Is there in internet address where I can report such things to Symantec?
I heard there is a platform for THINK C programmers.
+++++++++++++++++++++++++++
From: greeny@top.cis.syr.edu (J. S. Greenfield)
Organization: Syracuse University, CIS Dept.
Date: Mon, 15 Jun 92 13:23:22 EDT
In article <1992Jun15.142525.12835@sci.kun.nl> holwerda@sci.kun.nl (R.N.A. Holwerda) writes:
>
>The Think Pascal 4.0 Manual description of the behaveour of boolean operators
>is incorrect. It says that when your program evaluates
>
> boolexprA and boolexprB
>
>you can't be sure boolexprB will be evaluated because the result of the 'and'-
>expression will be false if boolexprA eveluates to false. Then there's no need
>to evaluate boolexprB.
>
>My tests indicate that this is incorrect. Even if boolexprA returns false,
>boolexprB will be evaluated. The similar thing holds for the 'or' operator.
I believe that you have misread the manual. The manual clearly does *not*
state that a partial-evaluation semantics is used. It states that a partial-
evaluation semantics *may* be used, or may not--and as an end-user programmer,
you are not able to predict which will occur. Therefore, you are cautioned
not to rely on either partial-evaluation or complete-evaluation semantics
being performed.
Of course, only Symantec can answer why this has been done, but I would venture
a guess that it was a matter of convenience for them. Code optimization
probably plays a large role in determining which boolean sub-expressions are
evaluated first and whether or not an expression ends up being evaluated by
(what appears to the programmer as) partial-evaluation semantics.
- --
J. S. Greenfield greeny@top.cis.syr.edu
(I like to put 'greeny' here,
but my d*mn system wants a
*real* name!) "What's the difference between an orange?"
+++++++++++++++++++++++++++
From: phils@chaos.cs.brandeis.edu (Phil Shapiro)
Date: 16 Jun 92 15:03:53 GMT
Organization: Symantec Corp.
>>>>> On Mon, 15 Jun 92 13:23:22 EDT, greeny@top.cis.syr.edu (J. S. Greenfield) said:
> In article <1992Jun15.142525.12835@sci.kun.nl> holwerda@sci.kun.nl (R.N.A. Holwerda) writes:
>>
>>The Think Pascal 4.0 Manual description of the behaveour of boolean
>>operators is incorrect. It says that when your program evaluates
>>
>> boolexprA and boolexprB
>>
>>you can't be sure boolexprB will be evaluated because the result of
>>the 'and'- expression will be false if boolexprA eveluates to false.
>>Then there's no need to evaluate boolexprB.
>>
>>My tests indicate that this is incorrect. Even if boolexprA returns
>>false, boolexprB will be evaluated. The similar thing holds for the
>>'or' operator.
> I believe that you have misread the manual. The manual clearly
> does *not* state that a partial-evaluation semantics is used. It
> states that a partial- evaluation semantics *may* be used, or may
> not--and as an end-user programmer, you are not able to predict
> which will occur. Therefore, you are cautioned not to rely on
> either partial-evaluation or complete-evaluation semantics being
> performed.
> Of course, only Symantec can answer why this has been done, but I
> would venture a guess that it was a matter of convenience for them.
> Code optimization probably plays a large role in determining which
> boolean sub-expressions are evaluated first and whether or not an
> expression ends up being evaluated by (what appears to the
> programmer as) partial-evaluation semantics.
The language reference section of the THINK Pascal user manual is
almost the same as the Pascal ANSI standard. In general, odd rules
like the one above are straight from the standard. The Pascal
standard, like the ANSI C one, frees the implementation from specifing
evaluation order in a number of cases, including assignment and
function arguments. Pascal also leaves order of evaluation of Boolean
expressions up to the implementation, which does allow for some code
optimization.
The '&' and '|' operators are known as short-circuit boolean
operators, and THINK Pascal's support for them is mentioned on p. 478
and p. 492. They're also referenced in the index under "boolean".
To email to Symantec Languages support directly, try either
D0152@Applelink.apple.com or 76666.2005@CompuServe.com.
-phil
- --
Phil Shapiro Software Engineer
Language Products Group Symantec Corporation
Internet: phils@cs.brandeis.edu
+++++++++++++++++++++++++++
From: peter@cujo.curtin.edu.au (Peter N Lewis)
Organization: NCRPDA, Curtin University
Date: Wed, 17 Jun 1992 04:40:52 GMT
In article <1992Jun15.142525.12835@sci.kun.nl>, holwerda@sci.kun.nl (R.N.A. Holwerda) writes:
> boolexprA and boolexprB
> you can't be sure boolexprB will be evaluated because the result of the 'and'-
> expression will be false if boolexprA eveluates to false. Then there's no need
> to evaluate boolexprB.
My THINK Pascal 4.0 manual says this:
"Boolean operators are somewhat unique in that the result of the operation
may often be determined by the examination of only one operand. For example,
the expression
(b<>0) and (a/b>10)
is known to have the value false if b=0 regardeless of the value of a.
However, the evaluation of the subexpression (a/b>10) %BOLD-ON% may or
may not %BOLD-OFF% be performed in the evaluation of this expression.
It is therefore best to assume that it will and avoid this kind of
expression."
Thats fairly clear cut. Of course it doesn't mention & and | here, nor
are they mentioned in the index (as and is for example). However, if
you look up short-circuit, there is a reference to (of all things :)
Appendix C "Porting to THINk Pascal" which says:
"Short circuit Booleans
THINK Pascal uses & and | operators for minimum evaluation of boolean
expressions. In this statement:
if (p<>nil) & (p^.name='') then ...
The second test (p^.name='') is performed only if the first test (p<>nil)
evaluated to true."
I distictly remember reading in there somewhere that short circuit boolean
operators have been around since before v4, perhaps since before 3?. I
looked but I couldn't find it anywhere, perhaps its in the TP3 manual...
Hands up who would like to see some more operators, like: BAND, BOR, BSL,
etc as operators, and + on strings (Please someone give me + for strings!).
Sigh, I remember the good old days when I programmed in Turbo Pascal on
the PC many years back, it had all of them, not to mention static arrays...
> P.S. Is there in internet address where I can report such things to Symantec?
> I heard there is a platform for THINK C programmers.
Now there is a good question...
Peter.
______________________________________________________________________
Peter N Lewis, NCRPDA, Curtin University peter@cujo.curtin.edu.au
GPO Box U1987, Perth WA 6001, AUSTRALIA FAX: +61 9 367 8141
+++++++++++++++++++++++++++
From: Bruce.Hoult@bbs.actrix.gen.nz
Date: Wed, 17 Jun 1992 12:06:52 GMT
Organization: Actrix Information Exchange
In article <1992Jun15.142525.12835@sci.kun.nl> holwerda@sci.kun.nl (R.N.A. Holwerda) writes:
>
> Has anyone else found any errors like this in the manual, or other undocumented
> features of the language or the envrinment? I'd really like to know.
The "problem" you described is the standard way for Pascal to work (on the
Mac at any rate). I'm not about to prove that it *isn't* documented in
the manual though :-)
Here's a genuine bug that I found in THINK Pascal 4.01: the alternative
form for GetMouse taking two integer Var parameters instead of a point
is no longer accepted -- a friend's program stopped compiling when she
took it from version 3 to 4.
According to the manual (p144, from memory) it is supposed to still work --
certainly the alternative forms of (Draw/Fill/Erase etc)(Rect/RoundRect/Oval
etc) with four integers instead of a Rect still work (the ones I tried anyway).
- -- Bruce
- --
Bruce.Hoult@bbs.actrix.gen.nz Twisted pair: +64 4 477 2116
BIX: brucehoult Last Resort: PO Box 4145 Wellington, NZ
"Cray's producing a 200 MIPS personal computer with 64MB RAM and a 1 GB
hard disk that fits in your pocket!" "Great! Is it PC compatable?"
---------------------------
From: zaccone@rigel.cs.bucknell.edu (Rick Zaccone)
Subject: Think C and ctype
Date: 16 Jun 92 14:57:51 GMT
Organization: Bucknell University, Lewisburg, Pa.
I'm trying to understand how Think C 5.0.2 implements the ctype
library.
The file ctype.c includes ctype.h. If I run the preprocessor on
ctype.c I get the following definition for isalnum. (Is this a
function definition?)
- ----------------------------------------------------------------------
int isalnum(int);
<Stuff Deleted>
extern char __ctype[];
int
(isalnum)(int c)
{
return((__ctype[(int) (unsigned char) (c)] & (64|128|16)));
}
- ----------------------------------------------------------------------
If I create a test program that uses isalnum and then run it through
the preprocessor, it gets expanded to the stuff returned by the
"return". So, Think C is (apparently) not using this function
definition although it *does* produce object code for it! (I verified
this by just compiling this function.) So what's going on here? Is
this just an intricate way of doing type checking for the macro
parameters? This looks somewhat like a function but I'm mystified by
the "(isalnum)". Is this a Think C extension to C? I haven't been
able to find it in the manual.
Rick Zaccone
- --
zaccone@bucknell.edu
+++++++++++++++++++++++++++
From: suitti@ima.isc.com (Stephen Uitti)
Organization: Interactive Systems, Cambridge, MA 02138-5302
Date: Tue, 16 Jun 1992 18:28:47 GMT
In article <ZACCONE.92Jun16105751@rigel.cs.bucknell.edu> zaccone@bucknell.edu writes:
>I'm trying to understand how Think C 5.0.2 implements the ctype
>library.
>
>The file ctype.c includes ctype.h. If I run the preprocessor on
>ctype.c I get the following definition for isalnum. (Is this a
>function definition?)
>
>----------------------------------------------------------------------
>int isalnum(int);
>
><Stuff Deleted>
>
>extern char __ctype[];
>int
>(isalnum)(int c)
>{
>return((__ctype[(int) (unsigned char) (c)] & (64|128|16)));
>}
>----------------------------------------------------------------------
>If I create a test program that uses isalnum and then run it through
>the preprocessor, it gets expanded to the stuff returned by the
>"return". So, Think C is (apparently) not using this function
>definition although it *does* produce object code for it! (I verified
>this by just compiling this function.) So what's going on here? Is
>this just an intricate way of doing type checking for the macro
>parameters? This looks somewhat like a function but I'm mystified by
>the "(isalnum)".
I recall that the ANSI C standard says that for these functions
you must have a real function, even if you provide a macro version.
That way, you can put function pointers to them into a table, and
it will work.
Now then, there are good reasons to make ctype functions macros.
Each of them does very little actual work. The function call
overhead would dominate. In fact, I recall a versions of UNIX
"spell" for the Vax, that spent over half of its time checking
isupper(), and calling tolower(). When these calls were inlined,
the spelling checker ran more than twice as fast (there were other
things that could have been done to "spell", and I saw a rewrite
that was over 8 times as fast).
For isalnum(), you could check to see if the character were alpha,
by calling isalpha(), or numeric, by calling isdigit():
#define isalnum(x) (isalpha(x) || isdigit(x))
And isalpha() could be written for ASCII to check ranges:
#define isalpha(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'a' && (x) <= 'z'))
And isdigit() could be written for ASCII to do a range check:
#define isdigit(x) ((x) >= '0' && (x) <= '9')
However, it is much faster to have a pre-computed array of flags, one
byte per flag. The character in question is used as an index into the
array. The array need be only 256 bytes long. There can be 8 flags.
One for "is this character a digit", one for "is this upper case",
one for "is this lower case", etc. This leads to a coding like:
__ctype[(int) (unsigned char) (c)] & (64|128|16)));
The two underscores for the array are so that the name does not
conflict with user code. ANSI C says that identifiers beginning
with two underscores are reserved for the system. The "&" is checking
for any of the specific bits set. Since FALSE is 0, and TRUE
is anything else, having isalnum() return 64 for some character
is OK.
>... Is this a Think C extension to C? I haven't been
>able to find it in the manual.
Think C certainly has extensions, but this isn't one of them.
Page 208 of the standard library reference manual doesn't say
that it is an extension, and it places the function in the ANSI
library. There is an error on page 208. It claims that
Each of these functions takes a single character c as an
argument. It returns 1 if c is a member of the category,
and a non-zero value if c isn't.
It should say that it returns a non-zero (TRUE) value is c is a
member, and zero (FALSE) if c isn't. Then, under Returns, page
209, it gets it backwards:
If c is... The function returns...
in the category 0 (zero).
not in the category non-zero.
When it should be:
If c is... The function returns...
in the category non-zero.
not in the category 0 (zero).
At least the example is correct (and is indented using K&R style,
as God intended ;-).
Stephen.
suitti@ima.isc.com
+++++++++++++++++++++++++++
From: mkahl@world.std.com (Michael Kahl)
Date: 17 Jun 92 10:04:20 GMT
Organization: The World Public Access UNIX, Brookline, MA
In article <ZACCONE.92Jun16105751@rigel.cs.bucknell.edu> zaccone@bucknell.edu writes:
>I'm trying to understand how Think C 5.0.2 implements the ctype
>library.
>
>The file ctype.c includes ctype.h. If I run the preprocessor on
>ctype.c I get the following definition for isalnum. (Is this a
>function definition?)
>
>----------------------------------------------------------------------
>int isalnum(int);
>
><Stuff Deleted>
>
>extern char __ctype[];
>int
>(isalnum)(int c)
>{
>return((__ctype[(int) (unsigned char) (c)] & (64|128|16)));
>}
>----------------------------------------------------------------------
>If I create a test program that uses isalnum and then run it through
>the preprocessor, it gets expanded to the stuff returned by the
>"return". So, Think C is (apparently) not using this function
>definition although it *does* produce object code for it! (I verified
>this by just compiling this function.) So what's going on here? Is
>this just an intricate way of doing type checking for the macro
>parameters? This looks somewhat like a function but I'm mystified by
>the "(isalnum)". Is this a Think C extension to C? I haven't been
>able to find it in the manual.
>
>Rick Zaccone
>--
>zaccone@bucknell.edu
Though it is certainly unusual to see redundant parentheses surrounding a
name in a function definition, they do not affect the meaning. However, if
they were omitted, the preprocessor would expand "isalnum" as a macro, just
as it does in the body. When a function-like macro (i.e. one with arguments)
appears not followed by a left parenthesis, it is protected from expansion;
surrounding the name in parentheses is one way to accomplish this. This is
not a THINK C extension; it is entirely according to the Standard.
The function definition is there, even though it is normally not used, in case
*you* use "isalnum" in such a way that it does not get macro-expanded. The
Standard says there has to be a real function there, backing up the macro as
it were, to cover this case.
- --
Michael Kahl mkahl@world.std.com
Disclaimer: Whoa! Did I say THAT??!
---------------------------
From: zobkiw@world.std.com (Joe Zobkiw)
Subject: dynamic 2d arrays in THINK C?
Organization: The World Public Access UNIX, Brookline, MA
Date: Wed, 17 Jun 1992 01:14:50 GMT
Does anyone have any information on where I might find some code to
implement dynamic 2-dimensional arrays in THINK C? 1-dimensions are easy
(aka Ptr) but 2-dimensions are a bit tougher to deal with in a nice, easy
manner.
Thanks in advance :)
- --
- -- joe zobkiw Internet: zobkiw@world.std.com
- -- AOL: AFL Zobkiw
- -- mac.synthesis.MIDI.THINK C.OOP
- -- asm.comm.networks.cool tunes...
+++++++++++++++++++++++++++
From: 9999cs02@uhdvx3 (Tina Marie!)
Organization: University of Houston-Downtown
Date: Wed, 17 Jun 1992 02:37:00 GMT
(Joe Zobkiw) writes...
>Does anyone have any information on where I might find some code to
>implement dynamic 2-dimensional arrays in THINK C? 1-dimensions are easy
>(aka Ptr) but 2-dimensions are a bit tougher to deal with in a nice, easy
>manner.
>
>Thanks in advance :)
>
Well, I don't have a reference, and I am not sure how nice and easy
you want this, but what's wrong with a dymanic array of Ptr's?? Say, like:
typedef struct
{
Ptr array[];
} niceType;
You can then reference it as (array[i])[j]....it doesn't get
much nicer or easier.
Tina Marie Femea
9999cs02@dt3.dt.uh.edu
+++++++++++++++++++++++++++
From: suitti@ima.isc.com (Stephen Uitti)
Organization: Interactive Systems, Cambridge, MA 02138-5302
Date: Wed, 17 Jun 1992 18:45:19 GMT
In article <Bpyu4r.1D8@world.std.com> zobkiw@world.std.com (Joe Zobkiw) writes:
>Does anyone have any information on where I might find some code to
>implement dynamic 2-dimensional arrays in THINK C? 1-dimensions are easy
>(aka Ptr) but 2-dimensions are a bit tougher to deal with in a nice, easy
>manner.
Here's a project that uses ANSI, oops libraries, one source, and
one header. It isn't what you want, but you should be able to
get what you want from it. It is developed in Think C 5. You
need C + Objects turned on in the options. It is lightly tested.
Consider it public, (no need to give credit, royalties, etc.). Enjoy.
Stephen.
suitti@ima.isc.com
####################
/* TwoDArray class header - two dimensional dynamic character array */
#ifndef _H_TWODARRAY
#define _H_TWODARRAY
struct TwoDArray : direct {
short numArrays; /* number of arrays */
short *lengths; /* array of lengths of each 1 D array */
char **arrays; /* pointers to arrays */
/* Methods */
void ITwoDArray(short y, short x); /* init to y by x, x is fastest moving */
void Dispose(void);
void setvalue(short y, short x, char val);
char getvalue(short y, short x);
};
#endif /* _H_TWODARRAY */
####################
/* TwoDArray.c
* Implement a two dimensional dynamic character array.
*/
#include "TwoDArray.h"
/* debug/test code */
#include <stdio.h>
#include <stdlib.h>
main()
{
register i;
register j;
struct TwoDArray *two;
two = new(TwoDArray);
two->ITwoDArray(3, 5);
for (i = 0; i < 3; i++) {
for (j = 0; j < 5; j++) {
two->setvalue(i, j, i * 10 + j);
}
}
for (i = 0; i < 3; i++) {
for (j = 0; j < 5; j++) {
printf("%d ", two->getvalue(i, j));
}
printf("\n");
}
two->Dispose();
}
/* init to y by x, x is fastest moving */
void TwoDArray::ITwoDArray(short y, short x)
{
register i;
/* range check on y & x */
if (x < 1 || y < 1) {
printf("Range error in ITwoDArray\n");
exit(1);
}
numArrays = y;
if ((lengths = malloc(sizeof(short) * numArrays)) == NULL) {
/* simple error check */
printf("Out of memory in ITwoDArray\n");
exit(1);
}
for (i = 0; i < numArrays; i++) {
lengths[i] = x;
if ((arrays[i] = malloc(x)) == NULL) {
/* error check */
printf("Out of memory in ITwoDArray\n");
exit(1);
}
}
}
void TwoDArray::Dispose(void)
{
register i;
if (lengths != NULL) {
free(lengths);
lengths = NULL;
}
if (arrays != NULL) {
for (i = 0; i < numArrays; i++) {
if (arrays[i] != NULL) {
free(arrays[i]);
}
}
free(arrays);
arrays = NULL;
}
}
void TwoDArray::setvalue(short y, short x, char val)
{
if (y >= numArrays) {
/* error check */
printf("bad setvale - (%d, %d) = %d\n", y, x, val);
return;
}
if (x >= lengths[y]) {
/* error check */
printf("bad setvale - (%d, %d) = %d\n", y, x, val);
return;
}
arrays[y][x] = val;
}
char TwoDArray::getvalue(short y, short x)
{
if (y >= numArrays) {
/* error check */
printf("bad getvale - (%d, %d) = %d\n", y, x);
return;
}
if (x >= lengths[y]) {
/* error check */
printf("bad getvale - (%d, %d) = %d\n", y, x);
return;
}
return arrays[y][x];
}
####################
---------------------------
End of C.S.M.P. Digest
**********************